# -*- coding: utf-8 -*-
"""
Created on Tue Jul  2 14:58:36 2024

@author: xiaobojie
"""

#%%动画不动

# python-- /, //, % 除，整除，取余
# c--      /, % 除，取余，没有整除



import argparse

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as anm


# 类似于c的宏?能否将255改为1
ON = 255
OFF = 0
vals = [ON, OFF]


def rand_grid(n):
    # np.random.choice从给定的列表[0,255]中选择一个值，每个值出现的概率
    # 由参数p=[0.1, 0.9]指定。这里，你要求0出现的概率是0.1（或10%），255出
    # 现的概率是90%（p中两个值相加必须等于1）。因为这个choice()方法创建了
    # 16个值的一维数组，所以用.reshape使它成为一个二维数组。
    return np.random.choice(vals, n*n, p=[0.2, 0.8]).reshape(n, n)



# 将glider增加到grid中，坐标是i,j
# 修改原array？
def add_glider(i, j, grid):
    glider = np.array([[0, 0, 255],
                       [255, 0, 255],
                       [0, 255, 255]])
    
    # grid数组切片
    grid[i:i+3, j:j+3] = glider
    
    
   
# 没使用frame
# 参数grid是array
def update(frame, img, grid, n):
    
    # new_grid是什么对象？
    new_grid = grid.copy()
    
    # 在每个元素上，求邻居ON的值
    for i in range(n):
        for j in range(n):
            
            # total记录元素邻居ON的数量
            # /255，是计算结果中有几个255
            # 取余，如果元素在边界，可以得到他的邻居，不在边界，取余数值不变
            total = int(
                (grid[i, (j-1)%n] + grid[i, (j+1)%n] +
                 grid[(i-1)%n, j] + grid[(i+1)%n, j] +
                 grid[(i-1)%n, (j-1)%n] + grid[(i-1)%n, (j+1)%n] +
                 grid[(i+1)%n, (j-1)%n] + grid[(i+1)%n, (j+1)%n])/255
                )
            
            # conway 生命条件
            if grid[i, j] == ON:
                if (total < 2) or (total > 3):
                    new_grid[i, j] = OFF
            else:
                if total == 3:
                    new_grid[i, j] = ON
    
    # img是什么对象？
    img.set_data(new_grid)
    
    # 更新grid
    grid[:] = new_grid[:]
    
    return img


def main():
    
    # 增加程序参数
    parser = argparse.ArgumentParser(description='运行conway生命模拟。')
    
    parser.add_argument('--grid_size', dest='n', required=False)
    parser.add_argument('--move_file', dest='move_file_a', required=False)
    parser.add_argument('--interval', dest='interval_a', required=False)
    # action='store_true'：这是一个特殊的动作参数，表示如果在命令行中出现了 --glider 这个选项，
    # 那么变量 args.glider 会被设置为 True，否则为 False。这种类型的参数通常称为布尔标志。
    parser.add_argument('--glider', action='store_true', required=False)
    parser.add_argument('--gosper', action='store_true', required=False)
    
    # 将参数保存为对象
    args = parser.parse_args()
    
    
    # 如果输入n，更新n的值
    n = 100
    if args.n and (int(args.n) > 8):
        n = int(args.n)
        
    update_inter = 50
    if args.interval_a:
        update_inter = int(args.interval_a)
        
    grid = np.array([])
    if args.glider:
        grid = np.zeros(n*n).reshape(n, n)
        add_glider(1, 1, grid)
        
    else:
        grid = rand_grid(n)
        
    # 开始绘图与动画    
    fig, ax = plt.subplots()
    img = ax.imshow(grid, interpolation='nearest')
    ani = anm.FuncAnimation(fig, update, fargs=(img, grid, n,), 
                            frames=10, interval=update_inter, save_count=50)
    
    if args.move_file_a:
        ani.save(args.move_file_a, fps=30, extra_args=['-vcodec', 'libx264'])
        
    plt.show()
    
    
    
if __name__ == '__main__':
    main()
    




#%%动画动了，查看代码区别

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as anm

# 修改 ON 和 OFF 的值
ON = 1
OFF = 0
vals = [ON, OFF]

def rand_grid(n):
    return np.random.choice(vals, n*n, p=[0.2, 0.8]).reshape(n, n)

def add_glider(i, j, grid):
    glider = np.array([[0, 0, 1],
                       [1, 0, 1],
                       [0, 1, 1]])
    grid[i:i+3, j:j+3] = glider

def update(frame, img, grid, n):
    print(f"Update frame: {frame}")  # 调试输出
    new_grid = grid.copy()
    for i in range(n):
        for j in range(n):
            total = int(
                (grid[i, (j-1)%n] + grid[i, (j+1)%n] +
                 grid[(i-1)%n, j] + grid[(i+1)%n, j] +
                 grid[(i-1)%n, (j-1)%n] + grid[(i-1)%n, (j+1)%n] +
                 grid[(i+1)%n, (j-1)%n] + grid[(i+1)%n, (j+1)%n])
            )
            if grid[i, j] == ON:
                if (total < 2) or (total > 3):
                    new_grid[i, j] = OFF
            else:
                if total == 3:
                    new_grid[i, j] = ON
    img.set_data(new_grid)
    grid[:] = new_grid[:]
    return img

def main():
    global _ani  # 声明全局变量
    n = 100
    update_inter = 50
    grid = rand_grid(n)
    
    # 如果需要 glider，可以在这里添加
    add_glider(1, 1, grid)
    
    fig, ax = plt.subplots()
    img = ax.imshow(grid, interpolation='nearest')
    _ani = anm.FuncAnimation(fig, update, fargs=(img, grid, n,), 
                            frames=200, interval=update_inter)
    
    plt.show()

if __name__ == '__main__':
    main()

